import moment from "moment";

export default {
    //#region UUID

    //生成全球唯一标识UUID
    GenerateUUID() {
        let d = new Date().getTime();
        if (window.performance && typeof window.performance.now === "function") {
            d += performance.now(); //use high-precision timer if available
        }
        let uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
            let r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
        });
        return uuid;
    },

    //根据RCF4122检查字符串是否为UUID
    IsUUID(uuid) {
        return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid);
    },

    //#endregion

    //#region 序列化与反序列化

    //将Json对象转换成Json字符串
    SerializeObject(jsonObj) {
        try {
            return JSON.stringify(jsonObj);
        } catch {
            return null;
        }
    },

    //将Json字符串转换成Json对象
    DeserializeObject(jsonStr) {
        if (this.IsEmpty(jsonStr)) {
            return null;
        }
        try {
            return JSON.parse(jsonStr);
        } catch {
            return null;
        }
    },

    //深度Copy对象
    DeepCopy(obj) {
        return this.DeserializeObject(this.SerializeObject(obj));
    },

    //#endregion

    //#region Cookie Session LocalSession 的操作

    //#region Cookie

    //将数据存储到Cookie中
    SetCookie(key, data) {
        document.cookie = key + "=" + this.SerializeObject(data) + ";path=/";
    },

    //获取Cookie中的数据
    GetCookie(key) {
        let name = key + "=";
        let allCookieStr = decodeURIComponent(document.cookie);
        let cookieArr = allCookieStr.split(";");
        for (let i = 0; i < cookieArr.length; i++) {
            let c = cookieArr[i];
            while (c.charAt(0) == " ") {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return this.DeserializeObject(c.substring(name.length, c.length));
            }
        }
        return null;
    },

    //移除指定Cookie中的数据
    RemoveCookie(key) {
        document.cookie = key + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
        document.cookie = key + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/";
    },

    //移除所有Cookie中的数据
    ClearCookie() {
        let keys = document.cookie.match(/[^ =;]+(?=\=)/g);
        if (!this.IsEmpty(keys) && keys.length > 0) {
            keys.forEach((key) => {
                this.RemoveCookie(key);
            });
        }
    },

    //#endregion

    //#region Session

    //将数据存储到Session中
    SetSession(key, data) {
        sessionStorage.setItem(key, this.SerializeObject(data));
    },

    //获取Session中的数据
    GetSession(key) {
        let strData = sessionStorage.getItem(key);
        if (this.IsEmpty(strData)) {
            return null;
        }
        return this.DeserializeObject(strData);
    },

    //移除指定Session中的数据
    RemoveSession(key) {
        sessionStorage.removeItem(key);
    },

    //移除所有Session中的数据
    ClearSession() {
        sessionStorage.clear();
    },

    //#endregion

    //#region LocalSession

    //将数据存储到LocalSession中
    SetLocalSession(key, data) {
        localStorage.setItem(key, this.SerializeObject(data));
    },

    //获取LocalSession中的数据
    GetLocalSession(key) {
        let strData = localStorage.getItem(key);
        if (this.IsEmpty(strData)) {
            return null;
        }
        return this.DeserializeObject(strData);
    },

    //移除指定LocalSession中的数据
    RemoveLocalSession(key) {
        localStorage.removeItem(key);
    },

    //移除所有LocalSession中的数据
    ClearLocalSession() {
        localStorage.clear();
    },

    //#endregion

    //#endregion

    //#region List与Tree的转换

    /**
     * 将List的数据转换成树形结构，子结点用children[]表示
     * @param list 源数据
     * @param idKey 主键名称
     * @param pidKey 父节点名称
     * @param isDelChildren 是否先删除list中的所有children
     * @returns
     */
    List2Tree(list, idKey, pidKey = "parentID", isDelChildren = true) {
        if (isDelChildren) {
            list.forEach((item) => {
                delete item.children;
            });
        }

        let map = {};
        list.forEach((item) => {
            map[item[idKey] || item.autoID] = item;
        });

        let res = [];

        for (let i = 0; i < list.length; i++) {
            let parent = map[list[i][pidKey]];

            if (parent) {
                (parent.children || (parent.children = [])).push(list[i]);
            } else {
                res.push(list[i]);
            }
        }

        return res;
    },

    /**
     * 将树形结构的数据转换成List
     * @param treeList 树形结构的数据
     * @returns
     */
    Tree2List(treeList) {
        let queen = [],
            res = [];
        queen = queen.concat(treeList);
        while (queen.length) {
            let temp = queen.shift();
            if (temp.children) {
                queen = temp.children.concat(queen);
                delete temp["children"];
            }
            res.push(temp);
        }
        return res;
    },

    //#endregion

    //#region 小数的四则运算

    /**
     * 计算2个数的相加，用于处理小数精度问题
     * @param arg1 数字1
     * @param arg2 数字2
     * @returns
     */
    Jia: function (arg1, arg2) {
        if (this.IsEmpty(arg1) || this.IsEmpty(arg2)) {
            return 0;
        }

        var r1, r2, m, c;
        try {
            r1 = arg1.toString().split(".")[1].length;
        } catch (e) {
            r1 = 0;
        }
        try {
            r2 = arg2.toString().split(".")[1].length;
        } catch (e) {
            r2 = 0;
        }
        c = Math.abs(r1 - r2);
        m = Math.pow(10, Math.max(r1, r2));
        if (c > 0) {
            var cm = Math.pow(10, c);
            if (r1 > r2) {
                arg1 = Number(arg1.toString().replace(".", ""));
                arg2 = Number(arg2.toString().replace(".", "")) * cm;
            } else {
                arg1 = Number(arg1.toString().replace(".", "")) * cm;
                arg2 = Number(arg2.toString().replace(".", ""));
            }
        } else {
            arg1 = Number(arg1.toString().replace(".", ""));
            arg2 = Number(arg2.toString().replace(".", ""));
        }
        return (arg1 + arg2) / m;
    },

    /**
     * 计算2个数的相减，用于处理小数精度问题
     * @param arg1 数字1
     * @param arg2 数字2
     * @returns
     */
    Jian: function (arg1, arg2) {
        if (this.IsEmpty(arg1) || this.IsEmpty(arg2)) {
            return 0;
        }

        var r1, r2, m, n;
        try {
            r1 = arg1.toString().split(".")[1].length;
        } catch (e) {
            r1 = 0;
        }
        try {
            r2 = arg2.toString().split(".")[1].length;
        } catch (e) {
            r2 = 0;
        }
        m = Math.pow(10, Math.max(r1, r2)); //last modify by deeka //动态控制精度长度
        n = r1 >= r2 ? r1 : r2;
        return Number(((arg1 * m - arg2 * m) / m).toFixed(n));
    },

    /**
     * 计算2个数的相乘，用于处理小数精度问题
     * @param arg1 数字1
     * @param arg2 数字2
     * @returns
     */
    Cheng: function (arg1, arg2) {
        if (this.IsEmpty(arg1) || this.IsEmpty(arg2)) {
            return 0;
        }
        var m = 0,
            s1 = arg1.toString(),
            s2 = arg2.toString();
        try {
            m += s1.split(".")[1].length;
        } catch (e) {}
        try {
            m += s2.split(".")[1].length;
        } catch (e) {}
        return (Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) / Math.pow(10, m);
    },

    /**
     * 计算2个数的相除，用于处理小数精度问题
     * @param arg1 数字1
     * @param arg2 数字2
     * @returns
     */
    Chu: function (arg1, arg2) {
        if (this.IsEmpty(arg1) || this.IsEmpty(arg2)) {
            return 0;
        }

        var t1 = 0,
            t2 = 0,
            r1,
            r2;
        try {
            t1 = arg1.toString().split(".")[1].length;
        } catch (e) {}
        try {
            t2 = arg2.toString().split(".")[1].length;
        } catch (e) {}

        r1 = Number(arg1.toString().replace(".", ""));
        r2 = Number(arg2.toString().replace(".", ""));
        return (r1 / r2) * Math.pow(10, t2 - t1);
    },
    //#endregion

    //#region 验证判断--字符串

    //验证对象是否为（null,undefined,""）
    IsEmpty(obj) {
        if (obj == null || obj == "undefined" || obj === "" || obj == undefined) {
            return true;
        } else {
            return false;
        }
    },

    //正则验证
    RegexMatch(reg, str) {
        return reg.test(str);
    },

    //验证是否为邮箱
    IsEmail(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^([a-zA-Z0-9]+[_|\_|\.])*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.])*[a-zA-Z0-9]+\.[a-zA-Z]{2,10}$/;
        return this.RegexMatch(reg, str);
    },

    //验证是否为手机号
    IsMobile(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^1[3|4|5|6|7|8|9][0-9]{9}$/;
        return this.RegexMatch(reg, str);
    },

    //验证是否为固定电话，可接受【区号-电话-分机】
    IsTel(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^((0\d{2,3})-)(\d{7,8})(-(\d{1,4}))?$/;
        return this.RegexMatch(reg, str);
    },

    //验证是否为手机号和固话
    IsPhone(str) {
        return this.IsMobile(str) || this.IsTel(str);
    },

    //验证是否为IP地址
    IsIp(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^(?:(?:1[0-9][0-9]\.)|(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9]))$/;
        return this.RegexMatch(reg, str);
    },

    //验证是否为中文
    IsChinese(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^[\u4e00-\u9fa5]{0,}$/;
        return this.RegexMatch(reg, str);
    },

    //是否为字母
    IsLetter(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^[A-Za-z]+$/;
        return this.RegexMatch(reg, str);
    },

    //是否为字母与数字
    IsLetterNumber(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^[A-Za-z0-9]+$/;
        return this.RegexMatch(reg, str);
    },

    //#endregion

    //#region 验证判断--数字

    /**
     * 验证是否为整数
     * @param  str 待验证的字符串
     * @returns
     */
    IsInt(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^-?\d+$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为正整数 x>0
     * @param  str 待验证的字符串
     * @returns
     */
    IsIntPositive(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^\+?[1-9][0-9]*$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为负整数 x<0
     * @param  str 待验证的字符串
     * @returns
     */
    IsIntNegative(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^\-[1-9][0-9]*$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为正整数 x>=0
     * @param  str 待验证的字符串
     * @returns
     */
    IsIntPositiveByZero(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^\d+$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为负整数 x<=0
     * @param  str 待验证的字符串
     * @returns
     */
    IsIntNegativeByZero(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^((-\d+)|(0+))$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为数字
     * @param  str 待验证的字符串
     * @returns
     */
    IsNumber(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^-?\d+(\.\d+)?$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为正数字 x>0
     * @param  str 待验证的字符串
     * @returns
     */
    IsNumberPositive(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为负数字 x<0
     * @param  str 待验证的字符串
     * @returns
     */
    IsNumberNegative(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为正数字 x>=0
     * @param  str 待验证的字符串
     * @returns
     */
    IsNumberPositiveByZero(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^\d+(\.\d+)?$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证是否为负数字 x<=0
     * @param  str 待验证的字符串
     * @returns
     */
    IsNumberNegativeByZero(str) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = /^((-\d+(\.\d+)?)|(0+(\.0+)?))$/;
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证小数位必需要有几位，不能没有小数位  eg:【1=false,1.=false,1.1=false,1.12=true,1.123=false】
     * @param str 待验证的字符串
     * @param n 小数位固定位数
     * @returns
     */
    HasPrecision(str, n = 2) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = new RegExp("^\\d+\\.\\d{" + n + "}?$");
        return this.RegexMatch(reg, str);
    },

    /**
     * 验证小数位不能小于且大于几位，可以没有小数位
     * @param str 待验证的字符串
     * @param max 最多几位小数
     * @param min 最少几位小数
     * @returns
     */
    MaxPrecision(str, max = 2, min = 1) {
        if (this.IsEmpty(str)) {
            return true;
        }
        str = str.trim();
        let reg = new RegExp("^\\d+(\\.\\d{" + min + "," + max + "})?$");
        return this.RegexMatch(reg, str);
    },

    //#endregion

    //#region 日期与时间

    /**
     * 根据date值返回日期部分
     * @param date 时间值，为null时则为当前时间
     * @returns
     */
    GetDate(date) {
        return this.FormatDate("YYYY-MM-DD", date);
    },

    /**
     * 根据date值返回时间部分
     * @param date 时间值，为null时则为当前时间
     * @returns
     */
    GetTime(date) {
        return this.FormatDate("HH:mm:ss", date);
    },

    /**
     * 根据date值返回日期与时间部分
     * @param date 时间值，为null时则为当前时间
     * @returns
     */
    GetDateTime(date) {
        return this.FormatDate("YYYY-MM-DD HH:mm:ss", date);
    },

    /**
     * 根据date值返回日期与时间部分，时间不返回秒
     * @param date 时间值，为null时则为当前时间
     * @returns
     */
    GetDateTimeHour(date) {
        return this.FormatDate("YYYY-MM-DD HH:mm", date);
    },

    /**
     * 格式化日期
     * @param format 格式化的字符，参考moment.js
     * @param date 时间值，为null时则为当前时间
     * @returns
     */
    FormatDate(format, date) {
        date = date == null ? new Date() : date;
        return moment(date).format(format);
    },

    /**
     * 用于返回日期/时间的单独部分
     * @param datePart 指定日期部分
     * @param date 日期
     * @returns
     */
    GetDatePart(datePart, date) {
        date = this.IsEmpty(date) ? new Date() : date;
        let m = moment(date);

        let res = Number.MIN_VALUE;
        switch (datePart) {
            case "year":
                res = m.year();
                break;
            case "month":
                res = m.month() + 1;
                break;
            case "date":
                res = m.date();
                break;
            case "hour":
                res = m.hour();
                break;
            case "minute":
                res = m.minute();
                break;
            case "second":
                res = m.second();
                break;
            case "millisecond":
                res = m.millisecond();
                break;
        }
        return res;
    },

    /**
     * 在日期中添加或减去指定的时间间隔
     * @param datePart 指定日期部分
     * @param val 值，可以是正数或负数
     * @param date 日期
     * @param format 返回指定日期格式
     * @returns
     */
    DateAdd(datePart, val, date, format) {
        date = this.IsEmpty(date) ? new Date() : date;
        let m = moment(date);

        if (this.IsEmpty(format)) {
            format = "YYYY-MM-DD HH:mm:ss";
        }

        switch (datePart) {
            case "year":
                m = m.add(val, "years");
                break;
            case "month":
                m = m.add(val, "months");
                break;
            case "date":
                m = m.add(val, "days");
                break;
            case "hour":
                m = m.add(val, "hours");
                break;
            case "minute":
                m = m.add(val, "minutes");
                break;
            case "second":
                m = m.add(val, "seconds");
                break;
            case "millisecond":
                m = m.add(val, "milliseconds");
                break;
        }
        return m.format(format);
    },

    /**
     * 返回两个日期之间的时间差【结束日期 - 开始日期】
     * @param datePart 指定日期部分
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @returns
     */
    DateDiff(datePart, startDate, endDate) {
        let start = moment(startDate);
        let end = moment(endDate);

        let res = Number.MIN_VALUE;
        switch (datePart) {
            case "year":
                res = end.diff(start, "years");
                break;
            case "month":
                res = end.diff(start, "months");
                break;
            case "date":
                res = end.diff(start, "days");
                break;
            case "hour":
                res = end.diff(start, "hours");
                break;
            case "minute":
                res = end.diff(start, "minutes");
                break;
            case "second":
                res = end.diff(start, "seconds");
                break;
            case "millisecond":
                res = end.diff(start, "milliseconds");
                break;
        }

        return res;
    },
    //#endregion

    YMD(date, nullValue = "-") {
        let res = nullValue;
        if (date) {
            let d = new Date(date);
            res = moment(d).format("YYYY-MM-DD");
        }
        return res;
    },

    //#region 格式化数字
    /**
     * 格式化数字，始终保留n位小数，n为要保留的小数位，超出则四舍五入，小于则补0
     * @param num 待格式化的数字
     * @param n 保留小数位
     * @returns
     */
    FormatNumber(num, n) {
        let resStr = num.toString();

        //当n>0时，说明要格式化成固定位数的小数形式
        if (n > 0) {
            let pos_decimal = resStr.indexOf(".");
            if (pos_decimal < 0) {
                //如果没有小数位，则给出小数点
                pos_decimal = resStr.length;
                resStr += ".";
            }

            //循环补0
            while (resStr.length <= pos_decimal + n) {
                resStr += "0";
            }
        }

        return resStr;
    },

    /**
     * 四舍五入数字，保留n位小数，小数位为0时则丢弃
     * @param num 待格式化的数字
     * @param n 保留小数位
     * @returns
     */
    GetRound(num, n) {
        let t = Math.pow(10, n);
        return Math.round(num * t) / t;
    },

    /**
     * 保留n位小数，多余小数位向下取整
     * @param num 待格式化的数字
     * @param n 保留小数位
     * @returns
     */
    GetFloor(num, n) {
        let t = Math.pow(10, n);
        return Math.floor(num * t) / t;
    },

    /**
     * 保留n位小数，多余小数位向上取整
     * @param num 待格式化的数字
     * @param n 保留小数位
     * @returns
     */
    GetCeil(num, n) {
        let t = Math.pow(10, n);
        return Math.ceil(num * t) / t;
    },
    //#endregion

    //#region GetRand 随机数

    /**
     * 得到一个范围内的随机数
     * @param min 范围最小值（包含）
     * @param max 范围最大值（包含）
     * @returns
     */
    GetRand(min, max) {
        return parseInt(Math.random() * (max - min) + min);
    },

    /**
     * 获取一个与时间相关的文件名
     * @param file File对象
     * @returns
     */
    GenerateFileName(file) {
        let fileInfo = this.GetUrlFileName(file.name);
        return fileInfo.fileName + "-" + new Date().getTime() + "." + fileInfo.extName;
    },

    //#endregion

    /**
     * 根据Url地址得到文件名信息
     * @param url Url地址
     * @returns
     */
    GetUrlFileName(url) {
        let res = {
            fileName: url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf(".")),
            extName: url.substring(url.lastIndexOf(".") + 1),
            fullName: url.substring(url.lastIndexOf("/") + 1),
        };
        return res;
    },

    // 按钮权限控制
    HasPermission(perID) {
        let store = getApp().globalData;
        if (this.IsEmpty(store) || this.IsEmpty(store.permissions) || store.permissions.length == 0) {
            return false;
        }
        let findItem = store.permissions.find((x) => x.perID == perID);
        if (this.IsEmpty(findItem)) {
            return false;
        } else {
            return findItem.isPermission;
        }
    },

    // 保留小数位
    inputFormatter(val, precision = 2) {
        if (val.indexOf(".") != -1) {
            let x = String(val).indexOf(".") + 1; //小数点的位置
            let y = String(val).length - x; //小数的位数
            if (precision == 0) {
                //整数
                let num = val.substr(0, val.indexOf("."));
                return num;
            }
            if (y > precision) {
                //小数
                let num = val.substr(0, val.indexOf(".") + (precision + 1));
                return num;
            }
            return val;
        }
        return val;
    },
};
